package com.xiaoy.web;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springside.modules.utils.web.ServletUtils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.opensymphony.xwork2.ActionSupport;
import com.xiaoy.util.bean.BeanUtils;
import com.xiaoy.util.json.IJsonBeanMapper;
import com.xiaoy.util.json.JSONUtils;

public class AsynAction  extends ActionSupport implements IJsonBeanMapper{

	private static final long serialVersionUID = -2667000788841211508L;
	
	private static final String HEADER_ENCODING = "encoding";
	private static final String HEADER_NOCACHE = "no-cache";
	private static final String DEFAULT_ENCODING = "UTF-8";
	private static final boolean DEFAULT_NOCACHE = true;
	
	// 属性区域  -------start 
	
	protected HttpServletRequest request = ServletActionContext.getRequest();
	protected HttpServletResponse response = ServletActionContext.getResponse();
	protected HttpSession session = request.getSession();
	protected ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(session.getServletContext());
	
	
	/**
	 * 取得HttpSession的简化函数.
	 */
//	public HttpSession getSession(boolean isNew) {
//		return request.getSession(isNew);
//	}
	
//	public Object getSessionAttribute(String name) {
//		HttpSession session = getSession(false);
//		return (session != null ? session.getAttribute(name) : null);
//	}


	private static ObjectMapper mapper = new ObjectMapper();
	
	/**
	 * 直接输出JSON.
	 * 
	 * @param jsonString
	 *            json字符串.
	 * @see #render(String, String, String...)
	 */
	public void renderJson(final String jsonString, final String... headers) {
		render(ServletUtils.JSON_TYPE, jsonString, headers);
	}
	
	/**
	 * 直接输出文本.
	 * 
	 * @see #render(String, String, String...)
	 */
	public void renderText(final String text, final String... headers) {
		render(ServletUtils.TEXT_TYPE, text, headers);
	}
	
	/**
	 * 直接输出HTML.
	 * 
	 * @see #render(String, String, String...)
	 */
	public void renderHtml(final String html, final String... headers) {
		render(ServletUtils.HTML_TYPE, html, headers);
	}
	
	/**
	 * 直接输出XML.
	 * 
	 * @see #render(String, String, String...)
	 */
	public void renderXml(final String xml, final String... headers) {
		render(ServletUtils.XML_TYPE, xml, headers);
	}
	
	/**
	 * 直接输出内容的简便函数.
	 * eg. render("text/plain", "hello", "encoding:GBK"); 
	 *     render("text/plain", "hello", "no-cache:false");
	 *     render("text/plain", "hello", "encoding:GBK", "no-cache:false");
	 * 
	 * @param headers
	 *            可变的header数组，目前接受的值为"encoding:"或"no-cache:",默认值分别为UTF-8和true.
	 */
	public void render(final String contentType, final String content, final String... headers) {
		HttpServletResponse response = initResponseHeader(contentType, headers);
		try {
			response.getWriter().write(content);
			response.getWriter().flush();
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}
	
	/**
	 * 直接输出JSON
	 * @param data
	 *            可以是List<POJO>, POJO[], POJO, 也可以Map名值对.
	 * @see #render(String, String, String...)
	 */
	public void renderJson(final Object data, final String... headers) {
		HttpServletResponse response = initResponseHeader(ServletUtils.JSON_TYPE, headers);
		try {
			mapper.writeValue(response.getWriter(), data);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
	}
	
	/**
	 * 直接输出支持跨域Mashup的JSONP.
	 * 
	 * @param callbackName
	 *            callback函数名.
	 * @param object
	 *            Java对象,可以是List<POJO>, POJO[], POJO ,也可以Map名值对, 将被转化为json字符串.
	 */
	public void renderJsonp(final String callbackName, final Object object, final String... headers) {
		String jsonString = null;
		try {
			jsonString = mapper.writeValueAsString(object);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}

		String result = new StringBuilder().append(callbackName).append('(').append(jsonString).append(");").toString();

		// 渲染Content-Type为javascript的返回内容,输出结果为javascript语句, 如callback197("{html:'Hello World!!!'}");
		render(ServletUtils.JS_TYPE, result, headers);
	}
	
	/**
	 * 分析并设置contentType与headers.
	 */
	private HttpServletResponse initResponseHeader(final String contentType, final String... headers) {
		// 分析headers参数
		String encoding = DEFAULT_ENCODING;
		boolean noCache = DEFAULT_NOCACHE;
		for (String header : headers) {
			String headerName = StringUtils.substringBefore(header, ":");
			String headerValue = StringUtils.substringAfter(header, ":");

			if (StringUtils.equalsIgnoreCase(headerName, HEADER_ENCODING)) {
				encoding = headerValue;
			} else if (StringUtils.equalsIgnoreCase(headerName, HEADER_NOCACHE)) {
				noCache = Boolean.parseBoolean(headerValue);
			} else {
				throw new IllegalArgumentException(headerName + "不是一个合法的header类型");
			}
		}

		// 设置headers参数
		String fullContentType = contentType + ";charset=" + encoding;
		response.setContentType(fullContentType);
		if (noCache) {
			ServletUtils.setNoCacheHeader(response);
		}
		return response;
	}
	
	
	@Override
	public String toJson(Object bean) {
		String s = JSONUtils.toJson(bean);
		return s;
	}
	@Override
	public <X> X fromJson(String jsonString, Class<X> pojoClass) {
		
		return JSONUtils.fromJson(jsonString,pojoClass);
	}
	@Override
	public <X> List<X> json2List(String jsonString, Class<X> pojoClass) {
		return JSONUtils.json2List(jsonString, pojoClass);
	}
	@Override
	public <X> List<X> json2Map(String jsonString, Class<X> pojoClass) {
		return JSONUtils.json2Map(jsonString, pojoClass);
	}
	

	
	public <T> T mapToBean(Class<T> clazz, Map<String, Object> map) {
		
		return BeanUtils.mapToBean(clazz, map);
	}

	/**
	 * JavaBean转Map   
	 * @param obj
	 * @return
	 */ 
	public Map<String, Object> beanToMap(Object obj) {
		
		return BeanUtils.beanToMap(obj);
	}
	
	
	
}


